import json
from django.http import JsonResponse
from django.views.generic import View
from ..serializers.departListSerializer import DepListQuerySerializer, DepListSerializer
from ..utils.literUtils import handle_serializer_error, emptyValue
from django.db.models import Q
from ..models.Department import Department
from ..models.Institution import Institution
from ..models.GlobalTables import InstitutionType, DepartmentType
from django.core.paginator import Paginator
from utils.encryptionAndDecryptionUtil import get_useraccount_from_request
from ..serializers.departInfoSerializer import DepartCreateSerializer, DepInfoSerializer
from ..serializers.instInfoSerializer import InstCreateSerializer
from datetime import datetime
import traceback
from control.models.User import User

class DepView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET    
            query_list_serializer = DepListQuerySerializer(data=data)
            data_valid = query_list_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res["message"] = "参数错误：" + \
                    handle_serializer_error(
                        errors=query_list_serializer.errors)
                return JsonResponse(res)
            data = query_list_serializer.validated_data
            deps = Department.objects.all().order_by('-create_date')
            query = Q()
            if "name" in data and data["name"] != "":
                query &= Q(name__icontains=data["name"])
            if "zh_name" in data and data["zh_name"] != "":
                query &= Q(zh_name__icontains=data["zh_name"])
            if 'dep_code' in data and data['dep_code'] != "":
                query &= Q(dep_code__icontains=data["dep_code"])
            if 'contact_number' in data and data['contact_number'] != "":
                query &= Q(contact_number__icontains=data["contact_number"])
            if 'email' in data and data['email'] != "":
                query &= Q(email__icontains=data["email"])
            if 'website' in data and data['website'] != "":
                query &= Q(website__icontains=data["website"])
            if 'founded_date' in data and data['founded_date'] != "":
                query &= Q(founded_date__icontains=data["founded_date"])
            if 'description' in data and data['description'] != "":
                query &= Q(description__icontains=data["description"])
            if 'dep_type' in data and len(data['dep_type']) != 0:
                dep_type_list = [x['[0]'] for x in data['dep_type']]
                query &= Q(dep_type_id__in=dep_type_list)

            order_list_combined = []
            prop_list = data.get('sort_prop', '').split(
                ',') if data.get('sort_prop') else []
            order_list = data.get('sort_order', '').split(
                ',') if data.get('sort_order') else []
            if len(prop_list) != len(order_list):
                res["code"] = 400
                res["message"] = "排序参数错误"
                return JsonResponse(res)
            for i in range(len(prop_list)):
                for prop, order in zip(prop_list, order_list):
                    if order.lower() == 'ascending':
                        order_list_combined.append(prop)
                    elif order.lower() == 'descending':
                        order_list_combined.append(f'-{prop}')
            if len(query) != 0:
                deps = deps.filter(query)
                
            tmp_insts = set()
            if 'institution' in data and data['institution'] != "":
                il = data['institution'].split(";")
                for i in il:
                    ii = i.strip()
                    ti = Institution.objects.filter(Q(name__icontains=ii) | Q(zh_name__icontains=ii))
                    for inst in ti.all():
                        tmp_insts.add(inst)
                # print(tmp_deps)
                deps = deps.filter(institution__in=tmp_insts)

            if len(order_list_combined) != 0:
                deps = deps.order_by(*order_list_combined)
            total_count = deps.count()
            res_data = {}
            if "page_size" in data:
                page_size = data["page_size"]
                current_page = data["current_page"]
                paginator = Paginator(deps, page_size)
                if current_page > paginator.num_pages:
                    current_page = paginator.num_pages
                page_obj = paginator.get_page(current_page)
                res_data["current_page"] = current_page
                res_data["page_size"] = page_size
                res_data["total_count"] = total_count
                dep_list_serializer = DepListSerializer(
                    page_obj, many=True)
                res_data["objects"] = dep_list_serializer.data
                res["code"] = 200
                res["message"] = "查询成功"
                res["data"] = res_data
                return JsonResponse(res)
            res_data["total_count"] = total_count
            dep_list_serializer = DepListSerializer(
                deps, many=True)
            res_data["objects"] = dep_list_serializer.data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = res_data
            return JsonResponse(res)
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def post(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            data['founded_date'] = None if emptyValue(data['founded_date']) else datetime.fromisoformat(data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
            data['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(data['dep_type']) else data['dep_type']
            
            inst_data = data['institution']
            inst = None
            if 'uuid' in inst_data:
                inst = Institution.objects.filter(uuid=inst_data['uuid'])[0]
            else:
                inst_data['founded_date'] = None if emptyValue(inst_data['founded_date'])  else datetime.fromisoformat(inst_data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                inst_data['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(inst_data['inst_type']) else inst_data['inst_type']
                inst_data.pop('departments', [])
            
                inst_add_serializer = InstCreateSerializer(data=inst_data)
                inst_data_valid = inst_add_serializer.is_valid()
                if not inst_data_valid:
                    print(inst_add_serializer.errors)
                    inst_serial_errors = handle_serializer_error(
                        errors=inst_add_serializer.errors)
                    res["code"] = 400
                    res["message"] = "参数错误：\n" + inst_serial_errors
                    return JsonResponse(res)
                inst_data = inst_add_serializer.validated_data
                inst_data["creator"] = u
                inst_data["last_editor"] = u
                inst = inst_add_serializer.save()
                
            data['institution'] = inst.uuid
                   
            add_serializer = DepartCreateSerializer(data=data)
            data_valid = add_serializer.is_valid()
            if not data_valid:
                print(add_serializer.errors)
                serial_errors = handle_serializer_error(
                    errors=add_serializer.errors)
                res["code"] = 400
                res["message"] = "参数错误：\n" + serial_errors
                return JsonResponse(res)
            data = add_serializer.validated_data
            data["creator"] = u
            data["last_editor"] = u
            
            add_serializer.save()
                
            res["code"] = 200
            res["message"] = "新建成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    
class DepInfoView(View):
    def get(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            dep = Department.objects.get(uuid=id)
            dep = DepInfoSerializer(dep).data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = dep
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def delete(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            d = Department.objects.get(uuid=id)
            if d is None:
                res["code"] = 400
                res["message"] = "该条目不存在"
                return JsonResponse(res)
            
            if len(d.author_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该部门仍被若干作者引用"
                return JsonResponse(res)
            
            if len(d.publication_set.all()) > 0:
                res["code"] = 400
                res["message"] = "删除失败：该部门仍被若干出版物引用"
                return JsonResponse(res)

            d.delete()
            res["code"] = 200
            res["message"] = "删除成功"
            res["data"] = None
        except Exception as e:
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    def put(self, request, id):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            u = User.objects.filter(user_account=user_name)[0]
            data = json.loads(request.body)
            data['founded_date'] = None if emptyValue(data['founded_date']) else datetime.fromisoformat(data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
            data['dep_type'] = DepartmentType.objects.filter(name='unknown')[0].uuid if emptyValue(data['dep_type']) else data['dep_type']
            
            inst_data = data['institution']
            inst = None
            if 'uuid' in inst_data:
                inst = Institution.objects.filter(uuid=inst_data['uuid'])[0]
            else:
                inst_data['founded_date'] = None if emptyValue(inst_data['founded_date'])  else datetime.fromisoformat(inst_data['founded_date'].replace('Z', '+00:00')).strftime("%Y-%m-%d")
                inst_data['inst_type'] = InstitutionType.objects.filter(name='unknown')[0].uuid if emptyValue(inst_data['inst_type']) else inst_data['inst_type']
                inst_data.pop('departments', [])
            
                inst_add_serializer = InstCreateSerializer(data=inst_data)
                inst_data_valid = inst_add_serializer.is_valid()
                if not inst_data_valid:
                    print(inst_add_serializer.errors)
                    inst_serial_errors = handle_serializer_error(
                        errors=inst_add_serializer.errors)
                    res["code"] = 400
                    res["message"] = "参数错误：\n" + inst_serial_errors
                    return JsonResponse(res)
                inst_data = inst_add_serializer.validated_data
                inst_data["creator"] = u
                inst_data["last_editor"] = u
                inst = inst_add_serializer.save()
                
            data['institution'] = inst.uuid
            
            dep = Department.objects.get(uuid=id)   
            modify_serializer = DepartCreateSerializer(instance=dep, data=data)
            data_valid = modify_serializer.is_valid()
            if not data_valid:
                print(modify_serializer.errors)
                serial_errors = handle_serializer_error(
                    errors=modify_serializer.errors)
                res["code"] = 400
                res["message"] = "参数错误：\n" + serial_errors
                return JsonResponse(res)
            data = modify_serializer.validated_data
            data["last_editor"] = u
            
            modify_serializer.save()
                
            res["code"] = 200
            res["message"] = "编辑成功"
            res["data"] = None
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)
    
    
class DepByInstView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET    
            deps = Department.objects.filter(institution_id=data["inst_uuid"])
            total_count = deps.count()
            res_data = {}
            res_data["total_count"] = total_count
            dep_list_serializer = DepListSerializer(
                deps, many=True)
            res_data["objects"] = dep_list_serializer.data
            res["code"] = 200
            res["message"] = "查询成功"
            res["data"] = res_data
            return JsonResponse(res)
        except Exception as e:
            traceback.print_exc()
            res["code"] = 500
            res["message"] = "服务器错误：" + str(e)
        return JsonResponse(res)